﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace EPiBoost.Core.CustomProperties.EnumSelector
{
	public static class EnumHelper
	{
		public static SelectedEnumCollection<T> GetEnumCollectionFromEnum<T>(bool excludeRemovedEnums) where T : struct
		{
			if(typeof(T).IsEnum)
			{
				var result = new SelectedEnumCollection<T>();

				var dictionary = GetDictinaryOfEnumAndAttribute<T>();

				dictionary = dictionary.OrderBy(x => x.Value.Order);
				
				if(excludeRemovedEnums)
				{
					dictionary = dictionary.Where(x => !x.Value.Removed);
				}

				foreach (var enumAndAttribute in dictionary)
				{
					result.Add(new SelectedEnum<T>(){Attributes = enumAndAttribute.Value, Value = (T)Enum.Parse(typeof(T),enumAndAttribute.Key)});
				}

				return result;
			}
			return null;
		}

		private static IEnumerable<KeyValuePair<string,EnumSelectorOptionAttribute>> GetDictinaryOfEnumAndAttribute<T>()
		{
			var type = typeof (T);
			var result = new Dictionary<string, EnumSelectorOptionAttribute>();

			foreach (FieldInfo field in type.GetFields(BindingFlags.Static | BindingFlags.GetField | BindingFlags.Public))
			{
				var att = GetAttributeFromField(field);
				result.Add(field.Name,att);
			}

			return result;
		}

		private static EnumSelectorOptionAttribute GetAttributeFromEnum<T>(T resultEnum)
		{
			var field = resultEnum.GetType().GetField(resultEnum.ToString());
			return GetAttributeFromField(field);
		}

		private static EnumSelectorOptionAttribute GetAttributeFromField(FieldInfo field)
		{
			EnumSelectorOptionAttribute att = new EnumSelectorOptionAttribute() { DisplayName = field.Name, Order = int.MaxValue };

			foreach (EnumSelectorOptionAttribute option in field.GetCustomAttributes(typeof(EnumSelectorOptionAttribute), false))
			{
				if (option != null)
				{
					att = option;
					break;
				}
			}
			return att;
		}


		internal static SelectedEnum<T> GetSelectedEnumFromString<T>(string str) where T : struct
		{
			T resultEnum;
			if(Enum.TryParse(str, out resultEnum))
			{
				var result = new SelectedEnum<T>();
				result.Value = resultEnum;
				result.Attributes = GetAttributeFromEnum(resultEnum);
				return result;
			}
			return null;
		}
	}
}
